package top.lywivan.netty.reactor;

import lombok.extern.slf4j.Slf4j;
import top.lywivan.netty.reactor.cnxn.ServerCnxn;
import top.lywivan.netty.reactor.cnxn.ServerCnxnFactory;
import top.lywivan.netty.reactor.model.Request;
import top.lywivan.netty.reactor.serialize.Serializer;

import java.nio.ByteBuffer;

@Slf4j
public class Server {

    public static final String GLOBAL_OUTSTANDING_LIMIT = "globalOutstandingLimit";
    // max 64
    public static final String NIO_NUM_BUSINESS_THREADS = "nio.numBusinessThreads";

    private int numBusinessThreads;// 业务线程池中的线程数

    private Serializer serializer;

    private State state;

    public void setSerializer(Serializer serializer) {
        this.serializer = serializer;
    }

    public Serializer getSerializer() {
        return serializer;
    }

    protected ServerCnxnFactory serverCnxnFactory;

    public void setServerCnxnFactory(ServerCnxnFactory serverCnxnFactory) {
        this.serverCnxnFactory = serverCnxnFactory;
    }


    private ServerShutDownHandler serverShutDownHandler;

    public void registerShutDownHandler(ServerShutDownHandler serverShutDownHandler) {
        this.serverShutDownHandler = serverShutDownHandler;
    }



    private BusinessService businessService;

    public void setBusinessService(BusinessService businessService) {
        this.businessService = businessService;
    }


    /**
     * 服务端处理数据
     * @param cnxn
     * @param incomingBuffer
     */
    public void processPacket(ServerCnxn cnxn, ByteBuffer incomingBuffer) {
        // 封装 request
        Request request = new Request(cnxn,incomingBuffer);

        // TODO throttled

        // submit request
        businessService.submitRequest(request);

    }

    public void startup() {
        startupWithState(State.RUNNING);
    }

    private void startupWithState(State state) {
        // 设置 业务线程池
        setupBusinessService();

        // 设置其他组件

        setState(state);
    }

    private void setState(State state) {
        this.state = state;

        if (serverShutDownHandler != null) {
            serverShutDownHandler.handle(state);
        }
    }

    private void setupBusinessService() {
        // 计算核心线程
        numBusinessThreads = Integer.getInteger(NIO_NUM_BUSINESS_THREADS,200);
        businessService = new BusinessService(this,numBusinessThreads,"Business");
    }

    protected enum State {
        INITIAL,
        RUNNING,
        SHUTDOWN,
        ERROR
    }



    public boolean shouldThrottle(long outStandingCount) {
        // 全局限流阈值
        int globalOutstandingLimit = getGlobalOutstandingLimit();
        // TODO THROTTLE

        /*if (globalOutstandingLimit < getInflight() || globalOutstandingLimit < getInProcess()) {
            return outStandingCount > 0;
        }
        return false;*/
        return false;
    }

    public int getGlobalOutstandingLimit() {
        Integer limit = Integer.getInteger(GLOBAL_OUTSTANDING_LIMIT, 1000);
        return limit.intValue();
    }

}
